package org.cqipc.edu.service.impl;

import org.cqipc.edu.common.Constants;
import org.cqipc.edu.common.StatusConstant;
import org.cqipc.edu.dao.*;
import org.cqipc.edu.entity.Plague_Info;
import org.cqipc.edu.entity.Swmd;
import org.cqipc.edu.entity.Userdie;
import org.cqipc.edu.entity.Userlife;
import org.cqipc.edu.service.PlagueService;
import org.cqipc.edu.utils.CommonUtil;
import org.cqipc.edu.vo.plague.plagueVo;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.Set;

/**
 * @Description: 瘟疫种类-接口实现
 * @ClassName: PlagueServiceImpl
 * @Author: Heyue
 * @DateTime: 2020-06-25
 **/
@Service
@Transactional
public class PlagueServiceImpl implements PlagueService {

    @Autowired
    private PlagueDao plagueDao;

    @Autowired
    private UserlifeDao userlifeDao;

    @Autowired
    private UserdieDao userdieDao;

    @Autowired
    private SwmdDao swmdDao;

    @Autowired
    private PlagueInfoDao plagueInfoDao;


    /**
     * @Description: 查询所有瘟疫信息
     * @Author: Heyue
     * @Date: 2020/6/25
     */
    @Override
    @Transactional(propagation = Propagation.SUPPORTS)
    public Object getPlagueAll() {
        return plagueDao.getPlagueAll();
    }


    /**
     * @Description: 根据ID查询瘟疫信息
     * @Author: Heyue
     * @Date: 2020/6/25
     */
    @Override
    @Transactional(propagation = Propagation.SUPPORTS)
    public Object getPlagueById(Integer id) {
        return plagueDao.getPlagueById(id);
    }


    /**
     * @Description: 根据瘟疫名称查询瘟疫信息
     * @Author: Heyue
     * @Date: 2020/6/25
     */
    @Override
    @Transactional(propagation = Propagation.SUPPORTS)
    public Object getPlagueByName(String name) {
        return plagueDao.getPlagueByName(name);
    }


    /**
     * @Description: 发布瘟疫处理
     * @Author: Heyue
     * @Date: 2020/6/25
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Object sendPlague(Integer plague, Integer area, Integer userlife, String description) {
        /*
        ==业务逻辑==
        1.查询该地区在生薄中的人员信息
        2.拿到该地区总共有多少人
        3.随机生成被感染人数(目前限制为20个)
        4.拿到被随即感染到的人的信息
        5.向瘟疫表中添加数据
        6.将数据转移到添加到死亡名单中(由于是批量添加，所有只需要死亡名单的集合即可)
        7.将数据转移到死表中，类型为病死
        8.将所有被感染者的ID放在一个集合，用于生薄批量删除
        9.回显数据：地区总人数；被感染人数；死亡人数
        注意：相当于把原有数据批量转移(添加)到死亡名单表和死薄表上，并且把生薄中的被感染者的信息按ID批量删除
        ==需求==
        1.瘟疫情况表添加SQL
        2.死薄/死亡名单批量添加SQL
        3.生薄批量删除SQL
         */

        //查询该地区在生薄中的人员信息
        List<Userlife> userlifeAll = userlifeDao.getUserlifeByAreaId(area);
        plagueVo vo = new plagueVo();
        boolean res = true;
        if (userlifeAll.size() > 1) {
            //取出感染体后的数据
            List<Userlife> newData = new ArrayList<>();
            for (Userlife userlife1 : userlifeAll) {
                if (userlife1.getLifeId() == userlife) {
                    continue;
                }
                newData.add(userlife1);
            }
            //在地区人数上生成随机人数感染上瘟疫
            //int i = new Random().nextInt(userlifeAll.size() + 1);
            /*临时限制感染人数为20之内*/
            Integer i = null;
            while (true) {
                i = new Random().nextInt(newData.size() + 1);
                if (i <= 20) {
                    break;
                } else {
                    continue;
                }
            }
            //向瘟疫情况表中添加的数据
            Plague_Info info = new Plague_Info();
            info.setAreaId(area)//设置地区ID
                    .setInfo(description)//设置描述
                    .setPlagueId(plague)//设置瘟疫类别
                    .setNumber(i)//设置感染人数
                    .setHappenTime(Constants.CURRENT_TIME)//设置瘟疫散布时间
                    .setUid(userlife)//设置感染体ID
                    .setDienumber(i + 1)//设置死亡人数
                    .setName(userlifeDao.getUserlifeById(userlife).getLifeName());//设置感染体姓名

            //随机生成被感染瘟疫人的编号，如过生成的随机ID用感染体相同则重新生成
            Set<Integer> randomNum = null;
            boolean flag = true;
            while (flag) {
                randomNum = CommonUtil.randomNum(i, newData.size());
                boolean a = true;
                for (Integer integer : randomNum) {
                    if (integer == userlife) {
                        a = false;
                    }
                }
                if (a) {
                    flag = false;
                }
            }
            //用于存放批量删除人的ID
            List<Integer> id = new ArrayList<>();
            //用户存放被感染者的信息
            List<Userlife> list = new ArrayList<>();
            //将随机生成的用户信息放到另一个数组方便进行操作
            for (Integer ran : randomNum) {
                Userlife userlife1 = new Userlife();
                BeanUtils.copyProperties(newData.get(ran), userlife1);
                list.add(userlife1);
                id.add(newData.get(ran).getLifeId());
            }
            //存入感染体的信息和ID
            id.add(userlife);
            list.add(userlifeDao.getUserlifeById(userlife));
            //向死薄批量添加信息的集合
            List<Userdie> userdies = new ArrayList<>();
            for (Userlife life : list) {
                Userdie userdie = new Userdie();
                userdie.setDieName(life.getLifeName())
                        .setDieSex(life.getLifeSex())
                        .setDieCountAge(life.getLifeCountAge())
                        .setDieAge(life.getLifeCurrentAge())
                        .setDieType(life.getLifeType())
                        .setDieWhy(4)
                        .setDieReinState(1)
                        .setDieReincarnation(null)
                        .setDieStatu(2)
                        .setDieArea(life.getLifeArea())
                        .setDieTime(Constants.CURRENT_TIME)
                        .setDieDesc("因" + plagueDao.getPlagueById(plague).getPlagueName() + "瘟疫而死")
                        .setDieCreatdate(Constants.CURRENT_TIME)
                        .setDieLassTime(Constants.CURRENT_TIME);
                userdies.add(userdie);
            }
            //向死亡名单批量添加信息的集合
            List<Swmd> swmds = new ArrayList<>();
            for (Userlife s : list) {
                Swmd swmd = new Swmd();
                swmd.setDid(s.getLifeId())
                        .setDname(s.getLifeName())
                        .setDsex(s.getLifeSex())
                        .setDage(s.getLifeCurrentAge())
                        .setDtime(Constants.CURRENT_TIME)
                        .setDarea(s.getLifeArea())
                        .setDfzid(userlife)
                        .setDtype(s.getLifeType());
                swmds.add(swmd);
            }
            userdieDao.batchAddDie(userdies);
            swmdDao.batchAddSwmd(swmds);
            userlifeDao.batchDelLive(id);
            plagueInfoDao.addPlagueInfo(info);
            //返回数据封装
            vo.setAreaCountNum(userlifeAll.size())
                    .setInfectedNum(i)
                    .setDieCountNum(list.size())
                    .setMsg(StatusConstant.MSG_SUCCESS)
                    .setStatusCode(200);
        } else {
            //向瘟疫情况表中添加的数据
            Plague_Info info = new Plague_Info();
            info.setAreaId(area)//设置地区ID
                    .setInfo(description)//设置描述
                    .setPlagueId(plague)//设置瘟疫类别
                    .setNumber(userlifeAll.size())//设置感染人数
                    .setHappenTime(Constants.CURRENT_TIME)//设置瘟疫散布时间
                    .setUid(userlife)//设置感染体ID
                    .setDienumber(userlifeAll.size())//设置死亡人数
                    .setName(userlifeDao.getUserlifeById(userlife).getLifeName());//设置感染体姓名

            //向死薄批量添加信息的集合
            List<Userdie> userdies = new ArrayList<>();
            Userdie userdie = new Userdie();
            Userlife life = userlifeDao.getUserlifeById(userlife);
            userdie.setDieName(life.getLifeName())
                    .setDieSex(life.getLifeSex())
                    .setDieCountAge(life.getLifeCountAge())
                    .setDieAge(life.getLifeCurrentAge())
                    .setDieType(life.getLifeType())
                    .setDieWhy(4)
                    .setDieReinState(1)
                    .setDieReincarnation(null)
                    .setDieStatu(2)
                    .setDieArea(life.getLifeArea())
                    .setDieTime(Constants.CURRENT_TIME)
                    .setDieDesc("因" + plagueDao.getPlagueById(plague).getPlagueName() + "瘟疫而死")
                    .setDieCreatdate(Constants.CURRENT_TIME)
                    .setDieLassTime(Constants.CURRENT_TIME);
            userdies.add(userdie);
            //向死亡名单批量添加信息的集合
            List<Swmd> swmds = new ArrayList<>();
            Swmd swmd = new Swmd();
            swmd.setDid(life.getLifeId())
                    .setDname(life.getLifeName())
                    .setDsex(life.getLifeSex())
                    .setDage(life.getLifeCurrentAge())
                    .setDtime(Constants.CURRENT_TIME)
                    .setDarea(life.getLifeArea())
                    .setDfzid(userlife);
            swmds.add(swmd);
            List<Integer> id = new ArrayList<>();
            id.add(userlife);
            userdieDao.batchAddDie(userdies);
            swmdDao.batchAddSwmd(swmds);
            userlifeDao.batchDelLive(id);
            plagueInfoDao.addPlagueInfo(info);
            //返回数据封装
            vo.setAreaCountNum(userlifeAll.size())
                    .setInfectedNum(userlifeAll.size())
                    .setDieCountNum(userlifeAll.size())
                    .setMsg(StatusConstant.MSG_SUCCESS)
                    .setStatusCode(200);
        }
        return res ? vo : StatusConstant.MSG_ERROR;
    }
}
